작성일 : 2024.10.09
내부 슬롯과 내부 메서드
- 내부 슬롯 : 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사야에서 사용하는 의사 프로퍼티 (pseudo property)
- 내부 메서도 : 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사야에서 사용하는 의사 메서드 (pseudo method)
-
- 개발자가 직접 접근할 수 있도록 외부로 공개된 객체의 프로퍼티가 아니다 *
프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
- JS 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동으로 정의한다.
- Porperty Attribute : [[Value]], [[Writable]], [[Enumerable]], [[Configurable]]
- Object.getOwnPropertyDescriptor 메서드를 사용하여 간접적으로 확인 가능
- Object.getOwnPropertyDescriptor 메서드는 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크럽터 객체를 반환
- 존재하지 않는 프로퍼티나 상속받은 프로퍼티에 대한 프로퍼티 디스크럽터를 요구하면 undefined 반환
const person = {
name: 'Lee'
};
person.age = 20;
console.log(Object.getOwnPropertyDescriptor(person));
console.log(Object.getOwnPropertyDescriptor(person,'name'));
데이터 프로퍼티와 접근자 프로퍼티
- 데이터 프로퍼티 : 키와 값으로 구성된 일반적인 프로퍼티
- 접근자 프로퍼티 : 자체적으로 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티
데이터 프로퍼티
| 프로퍼티 어트리뷰트 | 설명 |
|---|
| [[Value]] | 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는 값 |
| [[Writable]] | 프로퍼티 값의 변경 가능 여부 |
| [[Enumerable]] | 프로퍼티의 열거 가능 여부 for...in, Object.keys 메서드 등으로 열거 가능 여부 |
| [[Configurable]] | 프로퍼티의 재정의 가능 여부 |
- JS 엔진이 프로퍼티를 생성할 때 기본값으로 자동정의한다.
접근자 프로퍼티
| 프로퍼티 어트리뷰트 | 설명 |
|---|
| [[Get]] | 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수 |
| [[Set]] | 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수 |
| [[Enumerable]] | 프로퍼티의 열거 가능 여부 |
| [[Configurable]] | 프로퍼티의 재정의 가능 여부 |
- 동작 과정
- 프로퍼티 키가 유효한지 확인, 프로퍼티 키는 문자열 또는 심벌이어야 한다.
- 프로토타입 체인에서 프로퍼티를 검색
- 검색된 프로퍼티가 데이터 프로퍼티인지 접근자 프로퍼티인지 확인ㄴ
- 접근자 프로퍼티의 프로퍼티 어트리뷰트 [[Get]]의 값, getter 함수 호출하여 결과를 반환
프로퍼티 정의
| 프로퍼티 디스크립터의 프로퍼티 | 생략했을 때의 기본값 |
|---|
| value | undefined |
| get | undefined |
| set | undefined |
| writable | false |
| enumerable | false |
| configurable | false |
const person = {};
Object.defineProperty(person, 'firstName', {
value: 'Kee',
writable: true,
enumerable: true,
configurable: true
});
Object.defineProperty(person, 'lastName', {
value: 'JK'
});
Object.defineProperty(person, 'FullName', {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(name) {
[this.firstName, this,lastName] = name.split(' ');
},
enumerable: true,
configurable: true
});
person.fullName = "JK Park";
객체 변경 방지
| 구분 | 메서드 | 프로퍼티 추가 | 프로퍼티 삭제 | 프로퍼티 읽기 | 프로퍼티 쓰기 | 프토퍼티 재정의 |
|---|
| 객체 확장 금지 | Object.preventExtensions | X | O | O | O | O |
| 객체 밀봉 | Object.seal | X | X | O | O | X |
| 객체 동결 | Object.freeze | X | X | O | X | X |
객체 확장 금지
- Object.preventExtensions : 객체의 확장을 금지
- 확장이 금지된 객체는 프로퍼티 추가를 금지된다
const person = {name: 'jk'};
console.log(Object.isExtensiable(person));
Object.preventExtensions(person);
객체 밀봉
- Object.seal : 객체를 밀봉
- 밀봉된 객체는 읽기/쓰기만 가능
const person = {name: 'jk'};
console.log(Object.isSealed(person));
Object.seal(person);
객체 동결
- Object.freeze : 객체 동결
- 동결된 객체는 읽기만 가능
const person = {name: 'jk'};
console.log(Object.isFrozen(person));
Object.freeze(person);
- 3개의 변경방지 메서드들은 얕은 변경 방지로 직속 프로퍼티만 변경이 방지되고 중첩 객체까지는 영향을 못 준다.
- 불변 객체를 구현하기 위해선 객체를 값으로 갖는 모든 프로퍼티에 대해 재귀적으로 Object.freeze 메서드를 호출해야 한다.